渲染zh-Hant

recursive types

Translation status: 繁體中文 reader-locale proof. Term names and code fences follow the zh-Hant pack; supporting prose may still be English.

A 分支聯集 or 類型 may name itself in its own fields; every backend gives it a finite carrier.

Syntax: 分支聯集 <name> { <Variant> { <name> <field> } } · 類型 <name> { <name> ∪ 無 <field> }

Category#

type

Examples#

radix/corpus/recursio/expressio-arbor.fab (canonical · feature)#

A 分支聯集 or 類型 may name itself in its own fields; every backend gives it a finite carrier.

# =============================================================================
# recursive types — a type may refer to itself in its own fields.
# =============================================================================
#
# What this teaches:
#   • Recursive 分支聯集 — `Expr` variants hold `Expr` operands, so a value
#     is a whole expression tree. `比對` walks it recursively.
#   • Recursive 類型 — `Nodus` holds a nullable `Nodus` link, so a value is a
#     linked list ending in `無`.
#   • No keyword, no box type — Faber values alias by reference, so the
#     indirection is implied. Backends that store fields inline (Rust) insert
#     the pointer themselves on the fields that close the cycle.
#
# Common mistakes:
#   • A non-nullable self field on a 類型 (`Nodus next`) — no value can ever
#     be built, because every node needs another node. End the chain with
#     `∪ 無`, or recurse through a 分支聯集 with a leaf variant.
#
# See also: 分支聯集, 類型, 比對, 虛構, 無
# =============================================================================
#
# EXPECTED OUTPUT:
#   14
#   (2 + (3 * 4))
#   -9
#   6
#   3
#   2
#   15

union Expr {
    Numerus {
        int 值
    },
    Nega {
        Expr interior
    },
    Adde {
        Expr sinister
        Expr dexter
    },
    Multiplica {
        Expr sinister
        Expr dexter
    }
}

fn evalua(Expr e) → int {
    match e {
        case Numerus const 值 {
            return 值
        }
        case Nega const interior {
            return 0 - evalua(interior)
        }
        case Adde const sinister, dexter {
            return evalua(sinister) + evalua(dexter)
        }
        case Multiplica const sinister, dexter {
            return evalua(sinister) * evalua(dexter)
        }
    }
}

fn depinge(Expr e) → string {
    match e {
        case Numerus const 值 {
            return "§"(值)
        }
        case Nega const interior {
            return "-§"(depinge(interior))
        }
        case Adde const sinister, dexter {
            return "(§ + §)"(depinge(sinister), depinge(dexter))
        }
        case Multiplica const sinister, dexter {
            return "(§ * §)"(depinge(sinister), depinge(dexter))
        }
    }
}

class Nodus {
    var int 值
    var Nodus ∪ none sequens
}

fn 求和(Nodus ∪ none n) → int {
    if n is none {
        return 0
    }
    return n.valor + 求和(n.sequens)
}

fn longitudo(Nodus ∪ none n) → int {
    if n is none {
        return 0
    }
    return 1 + longitudo(n.sequens)
}

main {
    const Expr tres ← variant Numerus { 值 = 3 }
    const Expr productum ← variant Multiplica { sinister = tres, dexter = variant Numerus { 值 = 4 } }
    const Expr arbor ← variant Adde { sinister = variant Numerus { 值 = 2 }, dexter = productum }
    print evalua(arbor)
    print depinge(arbor)
    print evalua(variant Nega { interior = variant Adde { sinister = tres, dexter = variant Numerus { 值 = 6 } } })

    var Nodus caput ← Nodus { 值 = 1, sequens = Nodus { 值 = 2, sequens = Nodus { 值 = 3, sequens = null } } }
    print 求和(caput)
    print longitudo(caput)
    print caput?.sequens?.valor
    caput.sequens ← Nodus { 值 = 14, sequens = null }
    print 求和(caput)
}

Expected output:

14
(2 + (3 * 4))
-9
6
3
2
15